" File: myGrep.vim
" Author: Philippe Langlais
" Modification by LDE, to support double quote cf. 
" http://www.itnewsgroups.net/group/microsoft.public.windows.server.general/topic13123.aspx
" Of course, this character need to be anti-slashed. It works also for the dot
" char and others.
" Version: 1.0
" January 2003 / 2006
" 
" Overview
" --------
" The myGrep.vim plugin script integrates the windows findstr tool with Vim.
"
" Usage
" -----
" The myGrep.vim plugin script introduces the following commands:
"
" :Grep 'options' 'pattern' 'startdir' 'file pattern'
"       - Grep Recursivily for the specified pattern in the specified files
"
" When you run the one of the above commands, you will be prompted to enter
" the search pattern and the files in which to search for the pattern. By
" default, the keyword under the cursor will be displayed for the search
" pattern prompt.  Depending on the command, you may prompted for additional
" parameters like the directories to search for the pattern. The above
" commands will not accept the search pattern and the files as arguments.
"
" You can retrieve previously entered values for the Grep prompts using the up
" and down arrow keys. You can cancel the command by pressing the escape key.
" You can use CTRL-U to erase the default shown for the prompt and CTRL-W to
" erase the previous word in the prompt. For more information about editing
" the prompt, read :help cmdline-editing
"
" You can pass command-line options to the grep tools by appending them
" to the above commands. For example, to ignore case while searching for a
" pattern, you can use:
"
"       :Grep /I
"
" The output of the grep command will be listed in the Vim quickfix window.
" 1. You can select a line in the quickfix window and press <Enter> or double
"    click on a match to jump to that line.
" 2. You can use the ":cnext" and ":cprev" commands to the jump to the next or
"    previous output line.
" 3. You can use the ":colder" and ":cnewer" commands to go between multiple
"    grep quickfix output windows.
" 4. The quickfix window need not be opened always to use the grep output.
"    You can close the quickfix window and use the quickfix commands to jump
"    to the grep matches.  Use the ":copen" command to open the quickfix
"    window again.
"
" For more information about other quickfix commands read ":help quickfix"
" 
" Configuration
" -------------
" By changing the following variables you can configure the behavior of this
" script. Set the following variables in your .vimrc file using the 'let'
" command.
"
" By default, the '<F3>' key is mapped to run the ':Grep' command for the word
" under the cursor.  You can change this key by setting the 'Findstr_Key'
" variable:
"
"       let Findstr_Key = '<F9>'
"
" The 'Findstr_Path' variable is used to locate the grep utility. By default,
" this is set to /usr/bin/grep. You can change this using the let command:
"
"       :let Findstr_Path = 'findstr'
"
" When running any one of the Grep commands, you will be prompted for the
" files in which to search for the pattern. The 'Findstr_Default_Filelist'
" variable is used to specify to default for this prompt. By default, this
" variable is set to '*'. You can specify multiple matching patterns separated
" by spaces. You can change this settings using the let command:
"
"       :let Findstr_Default_Filelist = '*.c,*.h,*.pxs,*.s'
"
" The 'Findstr_Default_Options' is used to pass default command line options to
" the grep/fgrep/egrep/agrep utilities. By default, this is set to an empty
" string. You can change this using the let command:
"
"       :let Findstr_Default_Options = '/I'
"
" By default, when you invoke the Grep commands the quickfix window will be
" opened with the grep output.  You can disable opening the quickfix window,
" by setting the 'Findstr_OpenQuickfixWindow' variable  to zero:
"
"       :let Findstr_OpenQuickfixWindow = 0
"
" You can manually open the quickfix window using the :cwindow command.
"
" The 'Findstr_Shell_Quote_Char' variable specifies the quote character to use
" for protecting patterns from being interpreted by the shell. For Unix
" systems, this is set to '"' and for MS-Window systems, this is set to an
" empty string.  You can change this using the let command:
"
"       :let Findstr_Shell_Quote_Char = '"'
"
" --------------------- Do not modify after this line ---------------------
if exists("loaded_findstr") || &cp
    finish
endif
let loaded_findstr = 1
let g:tmpfile_grep = tempname()

" Location of the findstr utility with its options
if !exists("Findstr_Path") 
	if has("win32") || has("win64")
		let Findstr_Path = 'findstr'
		let Findstr_Options = '/s /n /r /p'
		let s:FileSep = "\\"
	else
		let Findstr_Path = 'grep -R -n'
		let s:FileSep = "/"
	endif
endif

" Open the Grep output window.  Set this variable to zero, to not open
" the Grep output window by default.  You can open it manually by using
" the :cwindow command.
if !exists("Findstr_OpenQuickfixWindow")
    let Findstr_OpenQuickfixWindow = 1
endif

" Default grep file list
if !exists("Findstr_Default_Filelist")
    let Findstr_Default_Filelist = '*.c,*.h,*.java'
endif

" Default grep options
if !exists("Findstr_Default_Options")
    let Findstr_Default_Options = ''
endif

" Key to invoke grep on the current word.  Modify this to whatever key
" you like
if !exists("Findstr_Key")
    let Findstr_Key = '<F3>'
endif

" Character to use to quote patterns and filenames before passing to grep.
if !exists("Findstr_Shell_Quote_Char")
    let Findstr_Shell_Quote_Char = '"'
endif

" --------------------- Do not edit after this line ------------------------

" Map a key to invoke grep on a word under cursor.
exe "nnoremap <unique> <silent> " . Findstr_Key . " :call <SID>RunGrepRecursive()<CR>"

" RunGrepCmd()
" Run the specified grep command using the supplied pattern
function! s:RunGrepCmd(cmd, pattern)
    
	if has("win32") || has("win64")
		" This is the basic solution using the cmd. Problem, you will see command
		" window for a short time while it executes.
		let ldecmd= "! cmd /C ".a:cmd 
		silent execute ldecmd
		" Using line below, goal is to no longer see the command window appearing
		" IT STILL DOES NOT WORK
		"let ldecmd= "! silentexec.exe -d \"cmd /C ".a:cmd."\""
	else " For Unix like
		let cmd_output = system(a:cmd)
		if cmd_output == ""
			echohl WarningMsg | 
					\ echomsg "Error: Pattern " . a:pattern . " not found" | 
					\ echohl None
			return
		endif

		exe "redir! > " . g:tmpfile_grep
		silent echon cmd_output
		redir END
	endif

    let old_efm = &efm
    set efm=%*[\ ]%f:%l:%m,%f:%l:%m

    execute 'silent! cfile '.g:tmpfile_grep

    let &efm = old_efm

    " Open the grep output window
    if g:Findstr_OpenQuickfixWindow == 1
        " Open the quickfix window below the current window
        botright copen
    endif

    " Jump to the first error
    cc

    call delete(g:tmpfile_grep)
endfunction

" RunGrepRecursive('pattern', 'startdir', 'files pattern')
" Run findstr command recursively
function! s:RunGrepRecursive(...)

    " Set default parameters
    let grep_opt = g:Findstr_Default_Options
    let pattern = expand("<cword>")
    let startdir = expand("%:p:h")
    let ext = expand("%:e")
    if g:Findstr_Default_Filelist !~ "*.".ext
        let g:Findstr_Default_Filelist = g:Findstr_Default_Filelist.",*.".ext
    endif
    let filepattern = g:Findstr_Default_Filelist

    " Get optional function parameters
    if a:0 >= 1
        let pattern = a:1
    endif
    if a:0 >= 2
        let startdir = a:2
    endif
    if a:0 >= 3
        let filepattern = a:3
    endif

    " If no argument supplied. Get the identifier and file list from user
    if a:0 < 1
        let pattern = inputdialog("Grep for pattern: \nNB: For special character, precede with \\ character. E.g. \\\" or \\..           ", pattern)
        if pattern == ""
            return
        endif
    endif

    if a:0 < 2
"        let startdir = browse(0, 'Start search dir', startdir, '')
        let startdir = inputdialog("Start searching from directory:\n".startdir,
                                   \ startdir)
        if startdir == ""
            return
        endif
		let startdir = substitute(startdir, "\\\\$","","")
    endif

    if a:0 < 3
        let filepattern = inputdialog("Grep ".pattern."\nFrom ".startdir."\nIn files matching pattern: ", filepattern)
        if filepattern == ""
            return
        endif
    endif

    " add Quote char to pattern
    let pattern = g:Findstr_Shell_Quote_Char . pattern . g:Findstr_Shell_Quote_Char
    " Extract file pattern
    let txt = filepattern . ','
	if has("win32") || has("win64")
		let find_file_pattern = ''
		while txt != ''
			let one_pattern = strpart(txt, 0, stridx(txt, ','))
			let find_file_pattern = find_file_pattern.'"'.startdir."\"".s:FileSep.one_pattern." "
			let txt = strpart(txt, stridx(txt, ',') + 1)
		endwhile
		let cmd = g:Findstr_Path." > ".g:tmpfile_grep." ".g:Findstr_Options." ".grep_opt." /C:".pattern." ".find_file_pattern
	else
		let cmd = g:Findstr_Path." ".grep_opt." ".pattern." --include={".filepattern."} " . startdir
	endif

    echo cmd
    call s:RunGrepCmd(cmd, pattern)

endfunction

" Define the set of grep commands
command! -nargs=* Grep call s:RunGrepRecursive(<f-args>)

